/*
 * Copyright (c) 2011-2020, hubin (jobob@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.baomidou.mybatisplus.generator.config.builder;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.IDbQuery;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.util.Column;
import com.baomidou.mybatisplus.generator.util.ColumnTable;
import com.baomidou.mybatisplus.generator.util.Util;

/**
 * <p>
 * 配置汇总 传递给文件生成工具
 * </p>
 *
 * @author YangHu, tangguo, hubin
 * @since 2016-08-30
 */
public class ConfigBuilder {

	/**
	 * 模板路径配置信息
	 */
	private final TemplateConfig template;
	/**
	 * 数据库配置
	 */
	private final DataSourceConfig dataSourceConfig;
	/**
	 * SQL连接
	 */
	private Connection connection;
	/**
	 * SQL语句类型
	 */
	private IDbQuery dbQuery;
	private String superEntityClass;
	private String superMapperClass;
	/**
	 * service超类定义
	 */
	private String superServiceClass;
	private String superServiceImplClass;
	private String superControllerClass;
	/**
	 * 数据库表信息
	 */
	private List<TableInfo> tableInfoList;
	/**
	 * 包配置详情
	 */
	private Map<String, String> packageInfo;
	/**
	 * 路径配置信息
	 */
	private Map<String, String> pathInfo;
	/**
	 * 策略配置
	 */
	private StrategyConfig strategyConfig;
	/**
	 * 全局配置信息
	 */
	private GlobalConfig globalConfig;
	/**
	 * 注入配置信息
	 */
	private InjectionConfig injectionConfig;

	/**
	 * <p>
	 * 在构造器中处理配置
	 * </p>
	 *
	 * @param packageConfig
	 *            包配置
	 * @param dataSourceConfig
	 *            数据源配置
	 * @param strategyConfig
	 *            表配置
	 * @param template
	 *            模板配置
	 * @param globalConfig
	 *            全局配置
	 */
	public ConfigBuilder(PackageConfig packageConfig, DataSourceConfig dataSourceConfig, StrategyConfig strategyConfig,
			TemplateConfig template, GlobalConfig globalConfig) {
		// 全局配置
		if (null == globalConfig) {
			this.globalConfig = new GlobalConfig();
		} else {
			this.globalConfig = globalConfig;
		}
		// 模板配置
		if (null == template) {
			this.template = new TemplateConfig();
		} else {
			this.template = template;
		}
		// 包配置
		if (null == packageConfig) {
			handlerPackage(this.template, this.globalConfig.getOutputDir(), new PackageConfig());
		} else {
			handlerPackage(this.template, this.globalConfig.getOutputDir(), packageConfig);
		}
		this.dataSourceConfig = dataSourceConfig;
		handlerDataSource(dataSourceConfig);
		// 策略配置
		if (null == strategyConfig) {
			this.strategyConfig = new StrategyConfig();
		} else {
			this.strategyConfig = strategyConfig;
		}
		handlerStrategy(this.strategyConfig);
	}

	// ************************ 曝露方法 BEGIN*****************************

	/**
	 * <p>
	 * 所有包配置信息
	 * </p>
	 *
	 * @return 包配置
	 */
	public Map<String, String> getPackageInfo() {
		return packageInfo;
	}

	/**
	 * <p>
	 * 所有路径配置
	 * </p>
	 *
	 * @return 路径配置
	 */
	public Map<String, String> getPathInfo() {
		return pathInfo;
	}

	public String getSuperEntityClass() {
		return superEntityClass;
	}

	public String getSuperMapperClass() {
		return superMapperClass;
	}

	/**
	 * <p>
	 * 获取超类定义
	 * </p>
	 *
	 * @return 完整超类名称
	 */
	public String getSuperServiceClass() {
		return superServiceClass;
	}

	public String getSuperServiceImplClass() {
		return superServiceImplClass;
	}

	public String getSuperControllerClass() {
		return superControllerClass;
	}

	/**
	 * <p>
	 * 表信息
	 * </p>
	 *
	 * @return 所有表信息
	 */
	public List<TableInfo> getTableInfoList() {
		return tableInfoList;
	}

	public ConfigBuilder setTableInfoList(List<TableInfo> tableInfoList) {
		this.tableInfoList = tableInfoList;
		return this;
	}

	/**
	 * <p>
	 * 模板路径配置信息
	 * </p>
	 *
	 * @return 所以模板路径配置信息
	 */
	public TemplateConfig getTemplate() {
		return template == null ? new TemplateConfig() : template;
	}

	// ****************************** 曝露方法 END**********************************

	/**
	 * <p>
	 * 处理包配置
	 * </p>
	 *
	 * @param template
	 *            TemplateConfig
	 * @param outputDir
	 * @param config
	 *            PackageConfig
	 */
	private void handlerPackage(TemplateConfig template, String outputDir, PackageConfig config) {
		// 包信息
		packageInfo = new HashMap<>(6);
		packageInfo.put(ConstVal.MODULE_NAME, config.getModuleName());
		// 自定义entity package
		if (Util.isNotEmpty(config.getEntityPackage())) {
			packageInfo.put(ConstVal.ENTITY, joinPackage("", config.getEntityPackage()));
		} else {
			packageInfo.put(ConstVal.ENTITY, joinPackage(config.getParent(), config.getEntity()));
		}
		// 自定义mapper package
		if (Util.isNotEmpty(config.getMapperPackage())) {
			packageInfo.put(ConstVal.MAPPER, joinPackage("", config.getMapperPackage()));
		} else {
			packageInfo.put(ConstVal.MAPPER, joinPackage(config.getParent(), config.getMapper()));
		}
		// 自定义xml package
		if (Util.isNotEmpty(config.getXmlPackage())) {
			packageInfo.put(ConstVal.XML, joinPackage("", config.getXmlPackage()));
		} else {
			packageInfo.put(ConstVal.XML, joinPackage(config.getParent(), config.getXml()));
		}
		// 自定义service package
		if (Util.isNotEmpty(config.getServicePackage())) {
			packageInfo.put(ConstVal.SERVICE, joinPackage("", config.getServicePackage()));
		} else {
			packageInfo.put(ConstVal.SERVICE, joinPackage(config.getParent(), config.getService()));
		}
		// 自定义 serviceImpl package
		if (Util.isNotEmpty(config.getServiceImplPackage())) {
			packageInfo.put(ConstVal.SERVICE_IMPL, joinPackage("", config.getServiceImplPackage()));
		} else {
			packageInfo.put(ConstVal.SERVICE_IMPL, joinPackage(config.getParent(), config.getServiceImpl()));
		}
		// 自定义controller package
		if (Util.isNotEmpty(config.getControllerPackage())) {
			packageInfo.put(ConstVal.CONTROLLER, joinPackage("", config.getControllerPackage()));
		} else {
			packageInfo.put(ConstVal.CONTROLLER, joinPackage(config.getParent(), config.getController()));
		}
		// 自定义路径
		Map<String, String> configPathInfo = config.getPathInfo();
		if (null != configPathInfo) {
			pathInfo = configPathInfo;
		} else {
			// 生成路径信息
			pathInfo = new HashMap<>(6);
			setPathInfo(pathInfo, template.getEntity(getGlobalConfig().isKotlin()), outputDir, ConstVal.ENTITY_PATH,
					ConstVal.ENTITY);
			setPathInfo(pathInfo, template.getMapper(), outputDir, ConstVal.MAPPER_PATH, ConstVal.MAPPER);
			setPathInfo(pathInfo, template.getXml(), outputDir, ConstVal.XML_PATH, ConstVal.XML);
			setPathInfo(pathInfo, template.getService(), outputDir, ConstVal.SERVICE_PATH, ConstVal.SERVICE);
			setPathInfo(pathInfo, template.getServiceImpl(), outputDir, ConstVal.SERVICE_IMPL_PATH,
					ConstVal.SERVICE_IMPL);
			setPathInfo(pathInfo, template.getController(), outputDir, ConstVal.CONTROLLER_PATH, ConstVal.CONTROLLER);
		}
	}

	private void setPathInfo(Map<String, String> pathInfo, String template, String outputDir, String path,
			String module) {
		if (StringUtils.isNotEmpty(template)) {
			pathInfo.put(path, joinPath(outputDir, packageInfo.get(module)));
		}
	}

	/**
	 * <p>
	 * 处理数据源配置
	 * </p>
	 *
	 * @param config
	 *            DataSourceConfig
	 */
	private void handlerDataSource(DataSourceConfig config) {
		connection = config.getConn();
		dbQuery = config.getDbQuery();
	}

	/**
	 * <p>
	 * 处理数据库表 加载数据库表、列、注释相关数据集
	 * </p>
	 *
	 * @param config
	 *            StrategyConfig
	 */
	private void handlerStrategy(StrategyConfig config) {
		processTypes(config);
		tableInfoList = getTablesInfo(config);
	}

	/**
	 * <p>
	 * 处理superClassName,IdClassType,IdStrategy配置
	 * </p>
	 *
	 * @param config
	 *            策略配置
	 */
	private void processTypes(StrategyConfig config) {
		if (StringUtils.isEmpty(config.getSuperServiceClass())) {
			superServiceClass = ConstVal.SUPER_SERVICE_CLASS;
		} else {
			superServiceClass = config.getSuperServiceClass();
		}
		if (StringUtils.isEmpty(config.getSuperServiceImplClass())) {
			superServiceImplClass = ConstVal.SUPER_SERVICE_IMPL_CLASS;
		} else {
			superServiceImplClass = config.getSuperServiceImplClass();
		}
		if (StringUtils.isEmpty(config.getSuperMapperClass())) {
			superMapperClass = ConstVal.SUPER_MAPPER_CLASS;
		} else {
			superMapperClass = config.getSuperMapperClass();
		}
		superEntityClass = config.getSuperEntityClass();
		superControllerClass = config.getSuperControllerClass();
	}

	/**
	 * <p>
	 * 处理表对应的类名称
	 * </P>
	 *
	 * @param tableList
	 *            表名称
	 * @param strategy
	 *            命名策略
	 * @param config
	 *            策略配置项
	 * @return 补充完整信息后的表
	 */
	private List<TableInfo> processTable(List<TableInfo> tableList, NamingStrategy strategy, StrategyConfig config) {
		String[] tablePrefix = config.getTablePrefix();
		for (TableInfo tableInfo : tableList) {
			String entityName = NamingStrategy.capitalFirst(processName(tableInfo.getName(), strategy, tablePrefix));
			// 如果没有表注释,默认实体名做注释 mlg
			if (StringUtils.isEmpty(tableInfo.getComment())) {
				tableInfo.setComment(entityName);
			}
			if (StringUtils.isNotEmpty(globalConfig.getEntityName())) {
				tableInfo.setConvert(true);
				tableInfo.setEntityName(String.format(globalConfig.getEntityName(), entityName));
			} else {
				tableInfo.setEntityName(strategyConfig, entityName);
			}
			if (StringUtils.isNotEmpty(globalConfig.getMapperName())) {
				tableInfo.setMapperName(String.format(globalConfig.getMapperName(), entityName));
			} else {
				tableInfo.setMapperName(entityName + "Dao" /* ConstVal.MAPPER */);
			}
			if (StringUtils.isNotEmpty(globalConfig.getXmlName())) {
				tableInfo.setXmlName(String.format(globalConfig.getXmlName(), entityName));
			} else {
				// mpper首字母小写
				tableInfo.setXmlName(entityName + ConstVal.MAPPER);
			}
			if (StringUtils.isNotEmpty(globalConfig.getServiceName())) {
				tableInfo.setServiceName(String.format(globalConfig.getServiceName(), entityName));
			} else {
				tableInfo.setServiceName(entityName + ConstVal.SERVICE);
			}
			if (StringUtils.isNotEmpty(globalConfig.getServiceImplName())) {
				tableInfo.setServiceImplName(String.format(globalConfig.getServiceImplName(), entityName));
			} else {
				tableInfo.setServiceImplName(entityName + ConstVal.SERVICE_IMPL);
			}
			if (StringUtils.isNotEmpty(globalConfig.getControllerName())) {
				tableInfo.setControllerName(String.format(globalConfig.getControllerName(), entityName));
			} else {
				tableInfo.setControllerName(entityName + ConstVal.CONTROLLER);
			}
			// 检测导入包
			checkImportPackages(tableInfo);
		}
		return tableList;
	}

	/**
	 * <p>
	 * 检测导入包
	 * </p>
	 *
	 * @param tableInfo
	 */
	private void checkImportPackages(TableInfo tableInfo) {
		if (StringUtils.isNotEmpty(strategyConfig.getSuperEntityClass())) {
			// 自定义父类
			tableInfo.getImportPackages().add(strategyConfig.getSuperEntityClass());
		} else if (globalConfig.isActiveRecord()) {
			// 无父类开启 AR 模式
			tableInfo.getImportPackages()
					.add(com.baomidou.mybatisplus.extension.activerecord.Model.class.getCanonicalName());
		}
		if (null != globalConfig.getIdType()) {
			// 指定需要 IdType 场景
			tableInfo.getImportPackages().add(com.baomidou.mybatisplus.annotation.IdType.class.getCanonicalName());
			tableInfo.getImportPackages().add(com.baomidou.mybatisplus.annotation.TableId.class.getCanonicalName());
		}
		if (StringUtils.isNotEmpty(strategyConfig.getVersionFieldName())) {
			tableInfo.getFields().forEach(f -> {
				if (strategyConfig.getVersionFieldName().equals(f.getName())) {
					tableInfo.getImportPackages()
							.add(com.baomidou.mybatisplus.annotation.Version.class.getCanonicalName());
				}
			});
		}
	}

	/**
	 * <p>
	 * 获取所有的数据库表信息
	 * </p>
	 */
	private List<TableInfo> getTablesInfo(StrategyConfig config) {
		boolean isInclude = (null != config.getInclude() && config.getInclude().length > 0);
		boolean isExclude = (null != config.getExclude() && config.getExclude().length > 0);
		if (isInclude && isExclude) {
			throw new RuntimeException("<strategy> 标签中 <include> 与 <exclude> 只能配置一项！");
		}
		// 所有的表信息
		List<TableInfo> tableList = new ArrayList<>();

		// 需要反向生成或排除的表信息
		List<TableInfo> includeTableList = new ArrayList<>();
		List<TableInfo> excludeTableList = new ArrayList<>();

		// 不存在的表名
		Set<String> notExistTables = new HashSet<>();
		PreparedStatement preparedStatement = null;
		try {
			String tablesSql = dbQuery.tablesSql();
			if (DbType.POSTGRE_SQL == dbQuery.dbType()) {
				String schema = dataSourceConfig.getSchemaName();
				if (schema == null) {
					// pg默认schema=public
					schema = "public";
					dataSourceConfig.setSchemaName(schema);
				}
				tablesSql = String.format(tablesSql, schema);
			}
			// oracle数据库表太多，出现最大游标错误
			else if (DbType.ORACLE == dbQuery.dbType()) {
				String schema = dataSourceConfig.getSchemaName();
				// oracle默认用户的schema=username
				if (schema == null) {
					schema = dataSourceConfig.getUsername().toUpperCase();
					dataSourceConfig.setSchemaName(schema);
				}
				tablesSql = String.format(tablesSql, schema);
				if (isInclude) {
					StringBuilder sb = new StringBuilder(tablesSql);
					sb.append(" AND ").append(dbQuery.tableName()).append(" IN (");
					Arrays.stream(config.getInclude()).forEach(
							tbname -> sb.append(StringPool.SINGLE_QUOTE).append(tbname.toUpperCase()).append("',"));
					sb.replace(sb.length() - 1, sb.length(), StringPool.RIGHT_BRACKET);
					tablesSql = sb.toString();
				} else if (isExclude) {
					StringBuilder sb = new StringBuilder(tablesSql);
					sb.append(" AND ").append(dbQuery.tableName()).append(" NOT IN (");
					Arrays.stream(config.getExclude()).forEach(
							tbname -> sb.append(StringPool.SINGLE_QUOTE).append(tbname.toUpperCase()).append("',"));
					sb.replace(sb.length() - 1, sb.length(), StringPool.RIGHT_BRACKET);
					tablesSql = sb.toString();
				}
			}
			preparedStatement = connection.prepareStatement(tablesSql);
			ResultSet results = preparedStatement.executeQuery();
			TableInfo tableInfo;
			while (results.next()) {
				String tableName = results.getString(dbQuery.tableName());
				if (StringUtils.isNotEmpty(tableName)) {
					String tableComment = results.getString(dbQuery.tableComment());
					if (config.isSkipView() && "VIEW".equals(tableComment)) {
						// 跳过视图
						continue;
					}
					tableInfo = new TableInfo();
					tableInfo.setName(tableName);
					tableInfo.setComment(tableComment);
					if (isInclude) {
						for (String includeTable : config.getInclude()) {
							// 忽略大小写等于 或 正则 true
							if (tableNameMatches(includeTable, tableName)) {
								includeTableList.add(tableInfo);
							} else {
								notExistTables.add(includeTable);
							}
						}
					} else if (isExclude) {
						for (String excludeTable : config.getExclude()) {
							// 忽略大小写等于 或 正则 true
							if (tableNameMatches(excludeTable, tableName)) {
								excludeTableList.add(tableInfo);
							} else {
								notExistTables.add(excludeTable);
							}
						}
					}
					tableList.add(tableInfo);
				} else {
					System.err.println("当前数据库为空！！！");
				}
			}

			// 将已经存在的表移除，获取配置中数据库不存在的表
			for (TableInfo tabInfo : tableList) {
				notExistTables.remove(tabInfo.getName());
			}
			if (notExistTables.size() > 0) {
				if (notExistTables.size() != 0 && !"[]".equals(notExistTables.toString())) {
					System.err.println("表 " + notExistTables + " 在数据库中不存在！！！");
				}
			}

			// 需要反向生成的表信息
			if (isExclude) {
				tableList.removeAll(excludeTableList);
				includeTableList = tableList;
			}
			if (!isInclude && !isExclude) {
				includeTableList = tableList;
			}
			/**
			 * 性能优化，只处理需执行表字段 github issues/219
			 */
			includeTableList
					.forEach(ti -> convertTableFields(ti, config.getColumnNaming(), config.getColumnTableList()));
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			try {
				if (preparedStatement != null) {
					preparedStatement.close();
				}
				if (connection != null) {
					connection.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return processTable(includeTableList, config.getNaming(), config);
	}

	/**
	 * <p>
	 * 表名匹配
	 * </p>
	 *
	 * @param setTableName
	 *            设置表名
	 * @param dbTableName
	 *            数据库表单
	 * @return
	 */
	private boolean tableNameMatches(String setTableName, String dbTableName) {
		return setTableName.equals(dbTableName) || StringUtils.matches(setTableName, dbTableName);
	}

	/**
	 * <p>
	 * 将字段信息与表信息关联
	 * </p>
	 *
	 * @param tableInfo
	 *            表信息
	 * @param strategy
	 *            命名策略
	 * @return
	 */
	private TableInfo convertTableFields(TableInfo tableInfo, NamingStrategy strategy,
			List<ColumnTable> columnTableList) {
		boolean haveId = false;
		List<TableField> fieldList = new ArrayList<>();
		List<TableField> commonFieldList = new ArrayList<>();
		try {
			String tableFieldsSql = dbQuery.tableFieldsSql();
			if (DbType.POSTGRE_SQL == dbQuery.dbType()) {
				tableFieldsSql = String.format(tableFieldsSql, dataSourceConfig.getSchemaName(), tableInfo.getName());
			} else if (DbType.ORACLE == dbQuery.dbType()) {
				tableFieldsSql = String.format(tableFieldsSql.replace("#schema", dataSourceConfig.getSchemaName()),
						tableInfo.getName());
			} else {
				tableFieldsSql = String.format(tableFieldsSql, tableInfo.getName());
			}
			PreparedStatement preparedStatement = connection.prepareStatement(tableFieldsSql);
			ResultSet results = preparedStatement.executeQuery();
			while (results.next()) {
				TableField field = new TableField();
				String key = results.getString(dbQuery.fieldKey());
				// 避免多重主键设置，目前只取第一个找到ID，并放到list中的索引为0的位置
				boolean isId;
				if (DbType.DB2 == dbQuery.dbType()) {
					isId = StringUtils.isNotEmpty(key) && "1".equals(key);
				} else {
					isId = StringUtils.isNotEmpty(key) && "PRI".equals(key.toUpperCase());
				}
				// 处理ID
				if (isId && !haveId) {
					field.setKeyFlag(true);
					if (dbQuery.isKeyIdentity(results)) {
						field.setKeyIdentityFlag(true);
					}
					haveId = true;
				} else {
					field.setKeyFlag(false);
				}
				// 自定义字段查询
				String[] fcs = dbQuery.fieldCustom();
				if (null != fcs) {
					Map<String, Object> customMap = new HashMap<>();
					for (String fc : fcs) {
						customMap.put(fc, results.getObject(fc));
					}
					field.setCustomMap(customMap);
				}
				// 处理其它信息
				field.setName(results.getString(dbQuery.fieldName()));
				field.setType(results.getString(dbQuery.fieldType()));
				field.setPropertyName(strategyConfig, processName(field.getName(), strategy));
				field.setColumnType(
						dataSourceConfig.getTypeConvert().processTypeConvert(globalConfig, field.getType()));
				field.setComment(results.getString(dbQuery.fieldComment()));
				if (strategyConfig.includeSuperEntityColumns(field.getName())) {
					// 跳过公共字段
					commonFieldList.add(field);
					continue;
				}
				// 填充逻辑判断
				List<TableFill> tableFillList = getStrategyConfig().getTableFillList();
				if (null != tableFillList) {
					// 忽略大写字段问题
					tableFillList.stream().filter(tf -> tf.getFieldName().equalsIgnoreCase(field.getName())).findFirst()
							.ifPresent(tf -> field.setFill(tf.getFieldFill().name()));
				}

				/** 添加typeHandler mlg */
				Set<String> importPackages = new HashSet<>();
				if (columnTableList != null && columnTableList.size() != 0) {
					Iterator<ColumnTable> it = columnTableList.iterator();
					while (it.hasNext()) {
						ColumnTable ob = it.next();
						// 同一张表
						if (tableInfo.getName().equals(ob.getTableName())) {
							// 添加到TableField中
							Iterator<Column> cit = ob.getColumn().iterator();
							while (cit.hasNext()) {
								Column c = cit.next();
								if (field.getName().equals(c.getColumnName())) {
									// 确保导包唯一性
									importPackages.add(c.getClazz());
									// importPackages.add(c.getHandlerClass());
									field.setColumn(c);
								}
							}
						}
					}
				}
				String[] packages = Util.converSetToArray(importPackages);
				if (packages.length != 0) {
					for (String pack : packages) {
						tableInfo.setImportPackages(pack);
					}
				}
				fieldList.add(field);
			}
		} catch (SQLException e) {
			System.err.println("SQL Exception：" + e.getMessage());
		}
		tableInfo.setFields(fieldList);
		tableInfo.setCommonFields(commonFieldList);
		return tableInfo;
	}

	/**
	 * <p>
	 * 连接路径字符串
	 * </p>
	 *
	 * @param parentDir
	 *            路径常量字符串
	 * @param packageName
	 *            包名
	 * @return 连接后的路径
	 */
	private String joinPath(String parentDir, String packageName) {
		if (StringUtils.isEmpty(parentDir)) {
			parentDir = System.getProperty(ConstVal.JAVA_TMPDIR);
		}
		if (!StringUtils.endsWith(parentDir, File.separator)) {
			parentDir += File.separator;
		}
		packageName = packageName.replaceAll("\\.", StringPool.BACK_SLASH + File.separator);
		return parentDir + packageName;
	}

	/**
	 * <p>
	 * 连接父子包名
	 * </p>
	 *
	 * @param parent
	 *            父包名
	 * @param subPackage
	 *            子包名
	 * @return 连接后的包名
	 */
	private String joinPackage(String parent, String subPackage) {
		if (StringUtils.isEmpty(parent)) {
			return subPackage;
		}
		return parent + StringPool.DOT + subPackage;
	}

	/**
	 * <p>
	 * 处理字段名称
	 * </p>
	 *
	 * @return 根据策略返回处理后的名称
	 */
	private String processName(String name, NamingStrategy strategy) {
		return processName(name, strategy, strategyConfig.getFieldPrefix());
	}

	/**
	 * <p>
	 * 处理表/字段名称
	 * </p>
	 *
	 * @param name
	 * @param strategy
	 * @param prefix
	 * @return 根据策略返回处理后的名称
	 */
	private String processName(String name, NamingStrategy strategy, String[] prefix) {
		boolean removePrefix = false;
		if (prefix != null && prefix.length >= 1) {
			removePrefix = true;
		}
		String propertyName;
		if (removePrefix) {
			if (strategy == NamingStrategy.underline_to_camel) {
				// 删除前缀、下划线转驼峰
				propertyName = NamingStrategy.removePrefixAndCamel(name, prefix);
			} else {
				// 删除前缀
				propertyName = NamingStrategy.removePrefix(name, prefix);
			}
		} else if (strategy == NamingStrategy.underline_to_camel) {
			// 下划线转驼峰
			propertyName = NamingStrategy.underlineToCamel(name);
		} else {
			// 不处理
			propertyName = name;
		}
		return propertyName;
	}

	public StrategyConfig getStrategyConfig() {
		return strategyConfig;
	}

	public ConfigBuilder setStrategyConfig(StrategyConfig strategyConfig) {
		this.strategyConfig = strategyConfig;
		return this;
	}

	public GlobalConfig getGlobalConfig() {
		return globalConfig;
	}

	public ConfigBuilder setGlobalConfig(GlobalConfig globalConfig) {
		this.globalConfig = globalConfig;
		return this;
	}

	public InjectionConfig getInjectionConfig() {
		return injectionConfig;
	}

	public ConfigBuilder setInjectionConfig(InjectionConfig injectionConfig) {
		this.injectionConfig = injectionConfig;
		return this;
	}
}
